from typing import Annotated

from fastapi import Depends, Request
from sqlalchemy import Integer, String, and_, func

from forward.api.h5.orm.contact import ContactORM
from forward.api.h5.orm.lucky.activity import ActivityORM
from forward.api.h5.orm.lucky.code import CodeORM
from forward.api.h5.orm.lucky.order import ActivityOrderORM
from forward.api.h5.orm.lucky.prize import PrizeORM
from forward.api.h5.orm.lucky.prize_temp import PrizeTempORM
from forward.api.h5.orm.merchant import MerchantORM
from forward.api.h5.orm.user import UserORM
from forward.api.h5.schemas.lucky.order import (
    ActivityCreateOrderInSchema,
    ActivityEditOrderInSchema,
    ActivityOrderDetailOutSchema,
)
from forward.api.h5.service.contact import ContactService
from forward.api.h5.service.lucky.code import CodeService
from forward.common.enums import (
    ActivitOrderStatusEnum,
    ActivityTypeEnum,
    CodeStatusEnum,
    PrizeLevelEnum,
)
from forward.exceptions.base import AppException
from forward.extend.pydantic.result_api import ResultAPI
from forward.http_base import HttpResp
from forward.model.schemas.contact import ContactSchema
from forward.model.schemas.lucky.order import ActivityOrderCreateSchema
from forward.model.tables.activity import ActivityOrderModel
from forward.utils.urls import UrlUtil


class OrderService:
    def __init__(
        self,
        request: Request,
        contact_service: Annotated[ContactService, Depends()],
        order_orm: Annotated[ActivityOrderORM, Depends()],
        prize_orm: Annotated[PrizeORM, Depends()],
        user_orm: Annotated[UserORM, Depends()],
        merchant_orm: Annotated[MerchantORM, Depends()],
        code_orm: Annotated[CodeORM, Depends()],
        prize_temp_orm: Annotated[PrizeTempORM, Depends()],
        activity_orm: Annotated[ActivityORM, Depends()],
        code_service: Annotated[CodeService, Depends()],
        contact_orm: Annotated[ContactORM, Depends()],
    ):
        self.contact_service = contact_service
        self.order_orm = order_orm
        self.prize_orm = prize_orm
        self.user_orm = user_orm
        self.merchant_orm = merchant_orm
        self.code_orm = code_orm
        self.activity_orm = activity_orm
        self.prize_temp_orm = prize_temp_orm
        self.code_service = code_service
        self.user_id = request.state.user_id
        self.contact_orm = contact_orm

    async def create(self, create_in: ActivityCreateOrderInSchema, user_id: int):
        """
        创建订单，没有新建 ，有的话 修改
        logic:
        1. 查询活动
        2. 查询商家
        3. 查询奖品
        4. 查询码号
        5. 查询用户
        6. 查询联系人
        7. 创建订单 实体
        8. 插入订单
        9. 修改码号状态
        10. 修改奖品抽奖状态
        11. 修改用户抽奖状态
        12. 修改联系人状态

        """

        activity = await self.activity_orm.get_one_by_id(create_in.activity_id)
        if not activity:
            raise AppException(exc=HttpResp.FAILED, msg="活动不存在")
        merchant = await self.merchant_orm.get_one_by_activity_id(create_in.activity_id)
        if not merchant:
            raise AppException(exc=HttpResp.FAILED, msg="商家不存在")
        prize = await self.prize_orm.get_one_by_id(create_in.prize_id)
        if not prize:
            raise AppException(exc=HttpResp.FAILED, msg="奖品不存在")
        code = await self.code_orm.get_one_by_filters(code=create_in.code)
        prize_temp = None
        if create_in.prize_temp_id:
            prize_temp = await self.prize_temp_orm.get_one_by_id(create_in.prize_temp_id)
        contact = None
        if create_in.contact_phone:
            contact = await self.contact_orm.create(
                ContactSchema(
                    address=create_in.contact_address,
                    mobile=create_in.contact_phone,
                    name=create_in.contact_name,
                    user_id=user_id,
                ).model_dump()
            )
        user = await self.user_orm.get_one_by_id(user_id)
        if not user:
            raise AppException(exc=HttpResp.FAILED, msg="用户不存在")
        # 实例化订单实体
        order_ = ActivityOrderCreateSchema(
            activity=activity,
            prize=prize,
            merchant=merchant,
            code=code,
            user=user,
            contact=contact,
            status=1,
            prize_temp=prize_temp
        )
        order = None
        # 查询订单
        if activity.type == ActivityTypeEnum.GUAGUALE.value:
            where = and_(
                func.json_extract(ActivityOrderModel.code,
                                  "$.code") == create_in.code,
            )
            order = await self.order_orm.get_one_by_filters(where=where)
        elif activity.type == ActivityTypeEnum.QRCODE.value:
            where = and_(
                func.json_extract(ActivityOrderModel.prize_temp,
                                  "$.id")
                == create_in.prize_temp_id,
            )

            order = await self.order_orm.get_one_by_filters(where=where)
        if not order:
            # 不存在 插入订单
            order = await self.order_orm.create(order_.model_dump(mode="json"))
        else:
            # 存在订单 修改
            order = await self.order_orm.update(order.id, order_.model_dump(mode="json"))
            print("update get order", order)

        return ResultAPI(data={"order": order})

    async def edit(self, order_id: int, edit_in: ActivityEditOrderInSchema, user_id: int):
        '''
        编辑订单：

        '''
        order = await self.order_orm.get_one_by_id(order_id)
        if not order:
            raise AppException(exc=HttpResp.FAILED, msg="订单不存在")
        if not order.contact:
            # 创建联系人
            contact = await self.contact_orm.create(
                ContactSchema(
                    name=edit_in.contact_name,
                    mobile=edit_in.contact_phone,
                    address=edit_in.contact_address,
                    user_id=user_id,
                ).model_dump()
            )
        else:
            # 更新联系人
            contact = await self.contact_orm.update(
                order.contact.id,
                ContactSchema(
                    name=edit_in.contact_name,
                    mobile=edit_in.contact_phone,
                    address=edit_in.contact_address,
                    user_id=user_id,
                ).model_dump()
            )
        if not contact:
            raise AppException(exc=HttpResp.FAILED, msg="创建联系人失败")
        # 更新订单快照中的联系人
        order = await self.order_orm.update(
            order_id,
            {
                "contact": contact.model_dump(mode="json"),
            }
        )
        return ResultAPI(data=order)

    async def order_list(self, user_id: int):
        """
        h5 订单列表
        订单状态 1 未核销 2 已核销
        """
        where = []

        # lists = await self.order_orm.get_all_by_filters(user_id=user_id)
        # lists = await self.order_orm.get_all_by_filters(id=94)
        where.append(
            func.json_extract(ActivityOrderModel.user, "$.id").cast(Integer)
            == self.user_id
        )
        order_list = await self.order_orm.get_all_by_filters(where=and_(*where))
        result_list = []
        for item in order_list:
            data = item.model_dump()
            data["prize"]["img"] = await UrlUtil.to_absolute_url(data["prize"]["img"])
            data["status_text"] = ActivitOrderStatusEnum.get_str(
                data["status"])
            data["activity"]["start_time"] = item.activity.start_time.strftime(
                "%Y-%m-%d"
            )
            data["activity"]["end_time"] = item.activity.end_time.strftime(
                "%Y-%m-%d"
            )
            data["prize_level_text"] = PrizeLevelEnum.get_label(
                item.code.prize_index) if item.code and item.code.prize_index is not None else ""

            activity_order = ActivityOrderDetailOutSchema(**data)
            result_list.append(activity_order)
        return ResultAPI(data=result_list)

    async def order_detail(self, order_id: int):

        order = await self.order_orm.get_one_by_id(id=order_id)
        if not order:
            raise AppException(exc=HttpResp.FAILED, msg="订单不存在")
        return ResultAPI(data=order)

    async def cancel(
        self,
        user_id: int,
        activity_id: int,
        code_: str | None = None,
        prize_temp_id: int | None = None,
    ):
        """
        核销码号
        改为 已抽奖
        """
        activity = await self.activity_orm.get_one_by_id(activity_id)
        if not activity:
            raise AppException(exc=HttpResp.FAILED, msg="活动不存在")
        if activity.type == ActivityTypeEnum.GUAGUALE:
            await self.cancle_guaguale(activity_id, code_, user_id)
        elif activity.type == ActivityTypeEnum.QRCODE:
            await self.cancle_qrcode(activity_id, prize_temp_id, user_id)

        return ResultAPI(data={}, msg="核销成功")

    async def cancle_qrcode(self, activity_id, temp_prize_id, user_id: int):
        # 修改用户缓存奖品的状态
        await self.prize_temp_orm.update(id=temp_prize_id, data={"status": 1})
        activity_qrcode_prize = await self.prize_temp_orm.get_one_by_id(temp_prize_id)
        if not activity_qrcode_prize:
            raise AppException(exc=HttpResp.FAILED, msg="奖品不存在")
        prize = await self.prize_orm.get_one_by_id(
            activity_qrcode_prize.prize_id if activity_qrcode_prize.prize_id else 0
        )
        if not prize:
            raise AppException(exc=HttpResp.FAILED, msg="奖品不存在")
        # await self.create(
        #     ActivityCreateOrderInSchema(
        #         activity_id=activity_id,
        #         prize_id=prize.id,
        #         temp_prize_id=temp_prize_id,
        #     ),
        #     user_id=user_id,
        # )
        return True

    async def cancle_guaguale(self, activity_id, code_, user_id):
        '''
        核销码号
        '''
        code = await self.code_orm.get_one_by_filters(code=code_)
        if not code:
            raise AppException(exc=HttpResp.FAILED, msg="码号不存在")
        if not code.prize_id:
            raise AppException(exc=HttpResp.FAILED, msg="码号未设置奖项")
        # 核销码号
        await self.code_service.chang_status(id=code.id, status=CodeStatusEnum.USED)
        # # 创建一个code订单
        # await self.create(
        #     ActivityCreateOrderInSchema(
        #         code=code_, activity_id=activity_id, prize_id=code.prize_id
        #     ),
        #     user_id=user_id,
        # )
        return True

    async def test(self):
        # where = and_(
        #     func.json_extract(ActivityOrderModel.code,
        #                       "$.code").cast(String) == "56iwlt",
        # )
        # where = []
        # where.append(
        #     func.json_extract(ActivityOrderModel.code,
        #                       "$.code").cast(String(50)) == "56iwlt",
        # )
        # order = await self.order_orm.get_one_by_filters(where=and_(*where))
        # print(order)
        order = await self.order_orm.get_one_by_id(id=123)
        print("order", order)
        return True
